;; Copyright © 2016, cage
;; All rights reserved.

;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are met:

;;     * Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;;     * Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.

;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
;; THE POSSIBILITY OF SUCH DAMAGE.

(in-package :mu-kanren-test)

(defsuite mu-kanren-suite (tests-suite))

(deftest mu-varp-test (mu-kanren-suite)
  (assert-true (mu-var-p (mu-var))))

(deftest mu-var=-test (mu-kanren-suite)
  (assert-true (mu-var= (mu-var 0) (mu-var 0))))

(deftest var-exists-in-subst-test (mu-kanren-suite)
  (assert-true (var-exists-in-subst-p (mu-var 2)
				      (list
				       (cons (mu-var 1)  1)
				       (cons (mu-var 2)  3)
				       (cons (mu-var 5)  8)))))

(deftest call/fresh-test (mu-kanren-suite)
  (let ((res      (funcall (call/fresh (lambda (q) (== q 5))) +empty-state+))
	(expected (list (cons (list (cons (mu-var) 5)) 1))))
    (assert-true (and (mu-var= (caaaar res)
			       (caaaar expected))
		      (=       (cdaaar res)
			       (cdaaar expected))
		      (=       (cdar   res)
			       (cdar   expected))))))

(defun a-and-b ()
  (conj
   (call/fresh (lambda (a) (== a 7)))
   (call/fresh (lambda (b) (disj (== b 5)
				 (== b 6))))))


(deftest conj/disj-test ()
  (assert-true
      (let ((res      (funcall (a-and-b) +empty-state+))
	    (expected (list (cons (list (cons (mu-var 1) 5) (cons (mu-var 0) 7))
				  2)
			    (cons (list (cons (mu-var 1) 6)
					(cons (mu-var 0) 7))
				  2))))
	(and (mu-var= (caaaar res)
		      (caaaar expected))
	     (=       (cdaaar res)
		      (cdaaar expected))
	     (mu-var= (car (cadaar res))
		      (car (cadaar expected)))
	     (=       (cdr (cadaar res))
		      (cdr (cadaar expected)))
	     (=       (cdar res)
		      (cdar expected))
	     (mu-var= (car (caaadr res))
		      (car (caaadr expected)))
	     (=       (cdr (caaadr res))
		      (cdr (caaadr expected)))
	     (mu-var= (caar (cdaadr res))
		      (caar (cdaadr expected)))
	     (mu-var= (cdar (cdaadr res))
		      (cdar (cdaadr expected)))
	     (=       (cdadr res)
		      (cdadr expected))))))
